home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 388_01 / ae / 93 / jul / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  7.0 KB  |  395 lines

  1. /*
  2.  * display.c        
  3.  *
  4.  * Anthony's Editor July 93
  5.  *
  6.  * Copyright 1993, 1993 by Anthony Howe.  All rights reserved.  No warranty.
  7.  */
  8.  
  9. #include <ctype.h>
  10. #include "header.h"
  11.  
  12. #ifdef __STDC__
  13. static void dispmsg(void);
  14. static int dispframe(void);
  15. static int dispchar(int, int, int);
  16. #else
  17. static void dispmsg();
  18. static int dispframe();
  19. static int dispchar();
  20. #endif
  21.  
  22. /*
  23.  * Reverse scan for start of logical line containing offset.
  24.  * 
  25.  *    offset <= 0    return    0
  26.  *    0 < offset    return    0 <= lnstart(offset) <= offset
  27.  */
  28. t_point
  29. lnstart(offset)
  30. register t_point offset;
  31. {
  32.     register int ch;
  33.  
  34.     /* Make sure that offset maps to a buffer location. */
  35.     if (offset <= 0)
  36.         return (0);
  37.  
  38.     /* Set up sentinel. */
  39.     ch = *buf;
  40.     *buf = '\n';
  41.  
  42.     /* Scan backwards for a newline. */
  43.     while (*ptr(--offset) != '\n')
  44.         ;
  45.  
  46.     /* Remove the sentinal. */
  47.     *buf = ch;
  48.  
  49.     /* Adjust offset provided offset != 0 or that we would
  50.      * have really found a newline instead of the sentinel.
  51.      */
  52.     if (offset != 0 || ch == '\n')
  53.         ++offset;
  54.  
  55.     return (offset);
  56. }
  57.  
  58. /*
  59.  * Forward scan for start of logical line following offset.
  60.  *
  61.  *    offset <= 0        return    1
  62.  *    pos(ebuf) <= offset    return    pos(ebuf)
  63.  *    0 < offset < pos(ebuf)    return    offset < lnnext(offset) <= pos(ebuf)
  64.  */
  65. t_point
  66. lnnext(off)
  67. register t_point off;
  68. {
  69.     register int ch;
  70.     register t_char *p;
  71.  
  72.     /* Set up sentinal. */
  73.     ch = ebuf[-1];
  74.     ebuf[-1] = '\n';
  75.  
  76.     /* Scan forwards for newline. */
  77.     while (*(p = ptr(off++)) != '\n')
  78.         ;
  79.  
  80.     /* Remove sentinal. */
  81.     ebuf[-1] = ch;
  82.  
  83.     /* Return offset immediately following a newline. */
  84.     return (pos(p)+1);
  85. }
  86.  
  87. /*
  88.  * Forward scan for start of logical line segment containing 'finish'.
  89.  * A segment of a logical line corresponds to a physical screen line.
  90.  */
  91. t_point
  92. segstart(start, finish)
  93. t_point start, finish;
  94. {
  95.     t_char *p;
  96.     int c = 0;
  97.     t_point scan = start;
  98.     while (scan < finish) {
  99.         p = ptr(scan);
  100.         if (*p == '\n') {
  101.             c = 0;
  102.             start = scan+1;
  103.         } else if (COLS <= c) {
  104.             c = 0;
  105.             start = scan;
  106.         }
  107.         ++scan;
  108.         c += *p == '\t' ? 8 - (c & 7) : 1;
  109.     }
  110.     return (c < COLS ? start : finish);
  111. }
  112.  
  113. /*
  114.  * Forward scan for start of logical line segment following 'finish'.
  115.  */
  116. t_point
  117. segnext(start, finish)
  118. t_point start, finish;
  119. {
  120.     t_char *p;
  121.     int c = 0;
  122.     t_point scan = segstart(start, finish);
  123.     for (;;) {
  124.         p = ptr(scan);
  125.         if (ebuf <= p || COLS <= c) 
  126.             break;
  127.         ++scan;
  128.         if (*p == '\n')
  129.             break;
  130.         c += *p == '\t' ? 8 - (c & 7) : 1;
  131.     }
  132.     return (p < ebuf ? scan : pos(ebuf));
  133. }
  134.  
  135. /*
  136.  * Move up one screen line.
  137.  */
  138. t_point
  139. upup(off)
  140. t_point off;
  141. {
  142.     t_point curr = lnstart(off);
  143.     t_point seg = segstart(curr, off);
  144.     if (curr < seg) 
  145.         off = segstart(curr, seg-1);
  146.     else
  147.         off = segstart(lnstart(curr-1), curr-1);
  148.     return (off);
  149. }
  150.  
  151. /*
  152.  * Move down one screen line.
  153.  */
  154. t_point
  155. dndn(off)
  156. t_point off;
  157. {
  158.     return (segnext(lnstart(off), off));
  159. }
  160.  
  161. /*
  162.  * Return the offset of a column on the specified line.
  163.  */
  164. t_point
  165. lncolumn(offset, column)
  166. t_point offset;
  167. int column;
  168. {
  169.     int c = 0;
  170.     t_char *p;
  171.     while ((p = ptr(offset)) < ebuf && *p != '\n' && c < column) {
  172.         c += *p == '\t' ? 8 - (c & 7) : 1;
  173.         ++offset;
  174.     }
  175.     return (offset);
  176. }
  177.  
  178. void
  179. display(fn)
  180. void (*fn) _((void));
  181. {
  182.     dispmsg();
  183.     if (dispframe() || marker != NOMARK)
  184.         dispfull();
  185.     else if (fn != NULL)
  186.         (*fn)();
  187.     move(row, col);
  188.     refresh();
  189. }
  190.  
  191. /*
  192.  * Full screen and cursor update.
  193.  */
  194. void
  195. dispfull()
  196. {
  197.     int i, j;
  198.     t_char *p;
  199.     t_region r;
  200.     
  201.     move(textline, 0);
  202.     i = textline;
  203.     j = 0;
  204.     epage = page;
  205.     getregion(&r);
  206.     for (;;) {
  207.         if (point == epage) {
  208.             row = i;
  209.             col = j;
  210.         }
  211.         p = ptr(epage);
  212.         if (LINES <= i || ebuf <= p)
  213.             break;
  214.         if (iscrlf(epage) != 1) {
  215.             if (marker != NOMARK) {
  216.                 if (point != epage
  217.                 && r.left <= epage && epage <= r.right)
  218.                     standout();
  219.                 else
  220.                     standend();
  221.             }
  222.             j = dispchar(j, (int) *p, TRUE);
  223.         }
  224.         if (*p == '\n' || COLS <= j) {
  225.             j -= COLS;
  226.             if (j < 0)
  227.                 j = 0;
  228.             ++i;
  229.         }
  230.         ++epage;
  231.     }
  232.     standend();
  233.     clrtobot();
  234.     if (++i < LINES)
  235.         mvaddstr(i, 0, getmsg(m_eof));
  236. }
  237.  
  238. /*
  239.  * Cursor update.
  240.  */
  241. void
  242. dispcursor()
  243. {
  244.     int i, j;
  245.     t_char *p;
  246.     t_point pt;
  247.     
  248.     i = textline;
  249.     j = 0;
  250.     pt = page;
  251.     for (;;) {
  252.         if (point == pt) {
  253.             row = i;
  254.             col = j;
  255.             break;
  256.         }
  257.         p = ptr(pt);
  258.         if (LINES <= i || ebuf <= p)
  259.             break;
  260.         if (iscrlf(pt) != 1)
  261.             j = dispchar(j, (int) *p, FALSE);
  262.         if (*p == '\n' || COLS <= j) {
  263.             j -= COLS;
  264.             if (j < 0)
  265.                 j = 0;
  266.             ++i;
  267.         }
  268.         ++pt;
  269.     }
  270.     standend();
  271. }
  272.  
  273. static int
  274. dispframe()
  275. {
  276.     int i, flag = FALSE;
  277.     
  278.     /* Re-frame the screen with the screen line containing the point
  279.      * as the first line, when point < page.  Handles the cases of a
  280.      * backward scroll or moving to the top of file.  pgup() will
  281.      * move page relative to point so that page <= point < epage.
  282.      */
  283.     if (point < page) {
  284.         page = segstart(lnstart(point), point);
  285.         flag = TRUE;
  286.     }
  287.     /* Re-frame the whole screen when epage <= point.  Handles the
  288.      * cases of a forward scroll or redraw.
  289.      */
  290.     if (epage <= point) {
  291.         /* Find end of screen plus one. */
  292.         page = dndn(point);
  293.         /* Number of lines on the screen depends if we are at the
  294.          * EOF and how many lines are used for help and status.
  295.          */
  296.         if (pos(ebuf) <= page) {
  297.             page = pos(ebuf);
  298.             i = LINES-2;
  299.         } else {
  300.             i = LINES;
  301.         }
  302.         i -= textline;
  303.         /* Scan backwards the required number of lines. */
  304.         while (0 < i--)
  305.             page = upup(page);
  306.         flag = TRUE;
  307.     }
  308.     return (flag);
  309. }
  310.  
  311. static int
  312. dispchar(col, ch, flag)
  313. int col, ch, flag;
  314. {
  315.     if (isprint(ch) || ch == '\t' || ch == '\n') {
  316.         col += ch == '\t' ? 8 - (col & 7) : 1;
  317.         if (flag)
  318.             addch(ch);
  319.     } else {
  320.         char *ctrl = printable(ch);
  321.         col += (int) strlen(ctrl);
  322.         if (flag)
  323.             addstr(ctrl);
  324.     }
  325.     return (col);
  326. }
  327.  
  328. static void
  329. dispmsg()
  330. {
  331.     standout();
  332.     move(MSGLINE, 0);
  333.     if (msgflag) {
  334.         addstr(msgline);
  335.         msgflag = FALSE;
  336.     } else if (modified) {
  337.         printw(getmsg(m_modified), filename);
  338.     } else {
  339.         printw(getmsg(m_file), filename, pos(ebuf));
  340.     }
  341.     standend();
  342.     clrtoeol();
  343. }
  344.  
  345. void
  346. ruler(ncols)
  347. int ncols;
  348. {
  349.     int r, c, col;
  350.     getyx(stdscr, r, c);
  351.     standout();
  352.     for (col = 1; col <= ncols; ++col) {
  353.         switch (col % 10) {
  354.         case 0:
  355.             mvprintw(r, col - (col < 100 ? 2 : 3), "%d", col);
  356.             break;
  357.         case 5:
  358.             addch('5');
  359.             break;
  360.         default:
  361.             addch('.');
  362.         }
  363.     }
  364.     standend();
  365. }
  366.  
  367. /*
  368.  * Convert byte ch into a printable character sequence.
  369.  * This mapping is for ASCII systems.
  370.  */
  371. char *
  372. printable(ch)
  373. unsigned ch;
  374. {
  375.     static char buf[5];
  376.     static char *mapping[] = {
  377.         "^?", 
  378.         "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", 
  379.         "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", 
  380.         "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", 
  381.         "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
  382.     };
  383.     if (ch == 0x7f) 
  384.         return (mapping[0]);
  385.     if (0 <= ch && ch < 32)
  386.         return (mapping[ch+1]);
  387.     if (isprint(ch)) {
  388.         buf[0] = ch;
  389.         buf[1] = '\0';
  390.     } else {
  391.         sprintf(buf, "\\%03o", ch);
  392.     }
  393.     return (buf);
  394. }
  395.